package com.rockwell.robot2015.model.states.running;

import com.rockwell.robot2015.model.RobotAction;
import com.rockwell.robot2015.model.states.IState;
import com.rockwell.robot2015.model.states.IStateMachine;
import com.rockwell.robot2015.model.states.running.sequence.ApproachingMazeSequence;
import com.rockwell.robot2015.model.states.running.sequence.ApproachingTreasureSequence;
import com.rockwell.robot2015.model.states.running.sequence.DroppingTreasureSequence;
import com.rockwell.robot2015.model.states.running.sequence.EnteringMazeDirectSequence;
import com.rockwell.robot2015.model.states.running.sequence.ExitingMazeSequence;
import com.rockwell.robot2015.model.states.running.sequence.FindingDropAreaSequence;
import com.rockwell.robot2015.model.states.running.sequence.FindingMazeEntranceSequence;
import com.rockwell.robot2015.model.states.running.sequence.FindingMazeSequence;
import com.rockwell.robot2015.model.states.running.sequence.FindingTreasureSequence;
import com.rockwell.robot2015.model.states.running.sequence.PickingTreasureSequence;

public enum RobotRunningState implements IState {
	
	FindingTreasure {
		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			FindingTreasureSequence sequence = m.findingTreasureSequence();
			sequence.start();
			
			machine.robot().log("Finding treasure", 2);
		}

		/**
		 * Turn the robot, detect treasures and choose the nearest one. 
		 * If a treasure is found, change to the ApproachingTreasure state.
		 */
		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			FindingTreasureSequence sequence = m.findingTreasureSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				machine.changeState(ApproachingTreasure);
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	ApproachingTreasure {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			ApproachingTreasureSequence sequence = m.approachingTreasureSequence();
			sequence.start();
			
			machine.robot().log("Approaching treasure", 2);
		}

		/**
		 * Jogging to the treasure
		 */
		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			ApproachingTreasureSequence sequence = m.approachingTreasureSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				machine.changeState(PickingTreasure);
			}
			else if (sequence.failed()) {
				machine.changeState(FindingTreasure);
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	PickingTreasure {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			PickingTreasureSequence sequence = m.pickingTreasureSequence();
			sequence.start();
			
			machine.robot().log("Picking treasure", 2);
		}

		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			PickingTreasureSequence sequence = m.pickingTreasureSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				if (machine.robot().isTieBreaker()) {
					machine.changeState(GameOver);
				}
				else {
					machine.changeState(FindingMaze);
				}
			}
			else if (sequence.failed()) {
				machine.changeState(FindingTreasure);
			}
			else {
				// ?
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	FindingMaze {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			FindingMazeSequence sequence = m.findingMazeSequence();
			sequence.start();
			
			machine.robot().log("Finding maze", 2);
		}

		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			FindingMazeSequence sequence = m.findingMazeSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				if (sequence.isMazeFound()) {
					machine.changeState(ApproachingMaze);
				}
				/*
				else if (sequence.isTreasureFound()) {
					machine.changeState(ApproachingTreasure);
				}
				*/
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	ApproachingMaze {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			ApproachingMazeSequence sequence = m.approachingMazeSequence();
			sequence.start();
			
			machine.robot().log("Approaching maze", 2);
		}

		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			ApproachingMazeSequence sequence = m.approachingMazeSequence();
			sequence.move();
			
			/*
			if (sequence.isAligned()) {
				machine.changeState(FindingMazeEntrance);
			}
			else if (sequence.foundEntranceFromFarAway()) {
				machine.changeState(EnteringMazeDirect);
			}*/
			if (sequence.succeeded()) {
				if (sequence.isAligned()) {
					machine.changeState(FindingMazeEntrance);
				}
				else if (sequence.alreadyInMaze()) {
					machine.changeState(FindingDroppingArea);
				}
				else {
					machine.changeState(FindingMazeEntrance);
				}
			}
			else if (sequence.failed()) {
				machine.changeState(FindingMaze);
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	EnteringMazeDirect {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			EnteringMazeDirectSequence sequence = m.enteringMazeDirectSequence();
			sequence.start();
		}

		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			EnteringMazeDirectSequence sequence = m.enteringMazeDirectSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				machine.changeState(FindingDroppingArea);
			}
			else if (sequence.failed()) {
				machine.changeState(FindingMaze);
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	FindingMazeEntrance {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			FindingMazeEntranceSequence sequence = m.findingMazeEntranceSequence();
			sequence.start();
			
			machine.robot().log("Finding maze entrance", 2);
		}

		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			FindingMazeEntranceSequence sequence = m.findingMazeEntranceSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				machine.changeState(FindingDroppingArea);
			}
			else if (sequence.failed()) {
				machine.changeState(FindingMaze);
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	/*
	EnteringMaze {

		@Override
		public void enter(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void move(IStateMachine machine) {
			machine.changeState(FindingDroppingArea);
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},*/
	FindingDroppingArea {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			FindingDropAreaSequence sequence = m.findingDropAreaSequence();
			ApproachingMazeSequence ams = m.approachingMazeSequence();
			sequence.setMazeType(ams.getMazeType());
			
			sequence.start();
			
			machine.robot().log("Finding drop area", 2);
		}

		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			FindingDropAreaSequence sequence = m.findingDropAreaSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				machine.changeState(DroppingTreasure);
			}
			else if (sequence.failed()) {
				machine.changeState(FindingMaze);
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	DroppingTreasure {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			DroppingTreasureSequence sequence = m.droppingTreasureSequence();
			sequence.start();
			
			machine.robot().log("Dropping treasure", 2);
		}

		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			DroppingTreasureSequence sequence = m.droppingTreasureSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				machine.changeState(ExitingMaze);
			}
			else {
				// ?
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	ExitingMaze {

		@Override
		public void enter(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			ExitingMazeSequence sequence = m.exitingMazeSequence();
			FindingDropAreaSequence fds = m.findingDropAreaSequence();
			sequence.setMazeType(fds.getMazeType());
			
			sequence.start();
			
			machine.robot().log("Exiting Maze", 2);
		}

		@Override
		public void move(IStateMachine machine) {
			RobotRunningStateMachine m = (RobotRunningStateMachine)machine;
			ExitingMazeSequence sequence = m.exitingMazeSequence();
			sequence.move();
			
			if (sequence.succeeded()) {
				machine.changeState(FindingTreasure);
			}
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	},
	
	GameOver {

		@Override
		public void enter(IStateMachine machine) {
			// TODO Send STOP command
			machine.robot().sendCommand(RobotAction.Stop);
		}

		@Override
		public void move(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void exit(IStateMachine machine) {
			// TODO Auto-generated method stub
			
		}
		
	};
}
